   import java.util.Arrays;
   import java.util.Calendar;
   import java.util.TimeZone;
/**
 * This class is instantiated to represent an Event object.  It uses Calendar Objects to represent start and end times.
 * It uses String Objects to hold other data associated with Event and contains getter and setter methods for them.
 * Methods prefixed with "ics" are specially formatted to output Strings to be interpreted as an iCal .ics file.
 * @author ICS 414 - Upgrade Project
 */
   public class Event {
      private String name;
      private Calendar timeNow;
      private Calendar start;
      private Calendar end;
		private Calendar endRecur;
      private String timeZone;	
      private String classification;
      private String path;
		private String directory;
		private String typeRecur;
      private String comment;
      private String location;
      private String resources;
      private boolean recur;
      private boolean[] recurring;
		
   
   /**
   * Constructor Method sets up three Calendar Objects identically at the current date-time with no leniency.
   * It also initializes all Strings to empty and defaults the repeat option to false.
   */
      public Event() {
         timeZone = "+00";
         timeNow = Calendar.getInstance();
         timeNow.setLenient(false);
         start = (Calendar)timeNow.clone();
         end = (Calendar)timeNow.clone();
         classification = "";
         path = "";
         comment = "";
         location = "";
         resources = "";
         recur = false;
			typeRecur = " ";
			endRecur = (Calendar)timeNow.clone();
      }
   
   // Setter Methods	
   
   /**
   * This method uses input to set time zones for start and end Date-Times.
   * @param String representing Time Zone formatted to set TimeZone as custom designated as
   * plus or minus GMT.
   */
      public void setTimeZone(String timeZone){
         this.timeZone = timeZone;
         start.setTimeZone(TimeZone.getTimeZone("GMT" + timeZone));
         end.setTimeZone(TimeZone.getTimeZone("GMT" + timeZone));
      }
   /**
    * This method takes five int parameters to set the Calendar for the start date-time for the Event.
    * The get method is called to ensure an exception is thrown when invalid date is set.
    * @param year int representing the year
    * @param month int representing the month (1 - 12)
    * @param date int representing the day of the month (date)
    * @param hour int representing the hour (00 - 23)
    * @param min int representing the minute (00 - 59)
    * @throws IllegalArgumentException observed when user inputs an invalid date (ex. February 31st)
    */
      public void setStart(int year, int month, int date, int hour, int min) throws IllegalArgumentException{
         start.set(year, month - 1, date, hour, min);
         start.get(Calendar.DAY_OF_WEEK);
      }
   /**
    * This method takes five int parameters to set the Calendar for the end date-time for the Event.
    * The get method is called to ensure an exception is thrown when invalid date is set.
    * @param year int representing the year
    * @param month int representing the month (1 - 12)
    * @param date int representing the day of the month (date)
    * @param hour int representing the hour (00 - 23)
    * @param min int representing the minute (00 - 59)
    * @throws IllegalArgumentException observed when user inputs an invalid date (ex. February 31st)
    */
      public void setEnd(int year, int month, int date, int hour, int minute) throws IllegalArgumentException{
         end.set(year, month - 1, date, hour, minute);
         end.get(Calendar.DAY_OF_WEEK);
      }
   
      public void setEndRecur(int year,int month,int date,int hour,int minute) throws IllegalArgumentException{
         endRecur.set(year,month - 1,date, hour, minute);
         endRecur.get(Calendar.DAY_OF_WEEK);
      }
   
   /**
    * Sets name to be used in output filename
    * @param name String from GUI input
    */
      public void setName(String name){
         this.name = name;
      }
   /**
    * Sets classification to be used in ics output file
    * @param classification String from GUI input
    */
      public void setClassification(String classification){
         this.classification = classification;
      }
      
   /**
    * Sets path to be with the path of where the ICS file outputs
    * @param path String from GUI input
    */
      public void setPath(String path){
         this.path = path;
      }
		
		public void setDirectory(String directory){
         this.directory = directory;
      }
		
   /**
    * Sets comment to be used in ics output file
    * @param comment String from GUI input
    */
      public void setComment(String comment){
         this.comment = comment;
      }
   /**
    * Sets location to be used in ics output file
    * @param location String from GUI input
    */
      public void setLocation(String location){
         this.location = location;
      }
   /**
    * Sets resources to be used in ics output file
    * @param resources String from GUI input
    */
      public void setResources(String resources){
         this.resources = resources;
		}
   /**
    * Sets values telling the program if an event will repeat and if so on which days of the week it will repeat.
    * @param repeat boolean true if repeating will occur, false if not
    * @param repeatDays boolean array of size 7, true for days of the week event will occur
    */
      public void setRecurring(boolean repeat, boolean[] repeatDays){
         this.recur = repeat;
         this.recurring = Arrays.copyOf(repeatDays, 7);
      }
		/** 
	*set value for type of recursion
	*/	
	      public void setTypeRecur(String typeRecur){
         this.typeRecur = typeRecur;
      }
   
   // Getter Methods
   /**
    * Getter method for name variable
    * @return String name
    */
      public String getName(){
         return name;
      }
   /**
    * Getter method for classification variable
    * @return String classification
    */
      public String getClassification(){
         return classification;
      }
   /**
    * Getter method for comment variable
    * @return String comment
    */
      public String getComment(){
         return comment;
      }
   /**
    * Getter method for location variable
    * @return String location
    */
      public String getLocation(){
         return location;
      }
   /**
    * Getter method for location variable
    * @return String location
    */
      public String getPath(){
         return path;
      }
		
		 public String getDirectory(){
         return directory;
      }
		
   /**
    * Getter method for resources variable
    * @return String resources
    */
      public String getResources(){
         return resources;
      }
		
		public String getTypeRecur(){
		return typeRecur;
		}
   /**
    * Getter method for String representation of timezone
    * @return String based on timezone of Calendar Object
    */
      public String getTimeZone(){
         return start.getTimeZone().getDisplayName();
      }
   /**
    * Method for String representation of start date-time for gui
    * @return String based on start Calendar Object
    */
      public String guiStart(){
         return guiDate(start);
      }
   /**
    * Method for String representation of end date-time for gui
    * @return String based on end Calendar Object
    */
      public String guiEnd(){
         return guiDate(end);
      }
   
      public String guiEndRecur(){
         return guiDate(endRecur);
      }
		
   /**
    * Helper method that takes a Calendar Object and formats an output String suitable for the GUI
    * @param cal Calendar Object to pull date-time from
    * @return String representation for use in GUI
    */
      private String guiDate(Calendar cal){
         return String.format("%1$tb %1$te, %1$tY %1$tH:%1$tM %1$tZ", cal);
      }
   /**
    * Method that creates a String to show weekly recursion based on boolean array 
    * @return String representation of recursion for use in GUI
    */
      public String guiRecurring(){
         String [] weekDays = {"Su ","Mo ","Tu ","We ","Th ","Fr ","Sa "};
         String result = "";
         if(recur){
            for(int i = 0; i < 7; i ++){
               if(recurring[i]){
                  result = result + weekDays[i];
               }
            }
         }
         return result;
      }
   /**
    * Method that creates a String for creation of .ics file
    * @return String representation of timeNow
    */
      public String icsNow(){
         return icsDate(timeNow);
      }
   /**
    * Method that creates a String for creation of .ics file
    * @return String representation of start
    */
      public String icsStart(){
         return icsDate(start);
      }
   /**
    * Method that creates a String for creation of .ics file
    * @return String representation of end
    */
      public String icsEnd(){
         return icsDate(end);
      }
      public String icsEndRecur(){
         return icsDate(endRecur);
      }
   /**
    * Helper method that creates a String readable according to RFC 5455 specifications
    * @return String representation of a date-time
    */
      private String icsDate(Calendar input){
         Calendar cal = (Calendar)input.clone();
         cal.add(Calendar.MILLISECOND, (-1) * cal.getTimeZone().getRawOffset());
         return String.format("%1$tY%1$tm%1$tdT%1$tH%1$tM00Z", cal);
      }
   /**
    * Method that creates a String for creation of .ics file
    * @return String representation of time zone offset
    */
      public String icsOffset(){
         return timeZone + "00";
      }
   /**
    * Method that creates a String for creation of .ics file
    * @return String representation of weekly recursion
    */	
      public String icsRecurring(){
         String[] days = {"SU","MO","TU","WE","TH","FR","SA"};
         String result = "";
      
         if(recur){
            result = result + "RRULE:FREQ=WEEKLY;BYDAY=";
            for(int i = 0; i < 7; i++){
               if(recurring[i]){
                  result = result + days[i] + ",";
               }
            }
            result = result.substring(0,result.length() - 1);
         }
         return result;
      }
   /**
    * Predicate method that determines if an end date-time is before a start date-time
    * @return boolean is true if start is on or preceeding end, false if not
    */
      public boolean valiDate(){
         if(start.compareTo(end) <= 0){
            return true;
         }
         else{
            return false;
         }
      }
      
      public boolean valiRecurDate(){
         if(start.compareTo(endRecur) <= 0){
            return true;
         }
         else{
            return false;
         }
      }
   /**
    * Method clears String fields to default when reset button is pressed
    */
      public void reset(){
         comment = "";
         location = "";
         resources = "";
         recur = false;
      }
   /**
    * Method mainly used for testing, gives a String output summary of Event Object variables
    */
      public String toString(){
      
         String result = "";
      
         result = result + "\nTime Zone: " + getTimeZone();
         result = result + "\nStart Time: " + guiStart();
         result = result + "\nEnd Time: " + guiEnd();
         result = result + "\nClassification: " + getClassification();
         result = result + "\nComment: " + getComment();
         result = result + "\nLocation: " + getLocation();
         result = result + "\nResources: " + getResources();
         result = result + "\nICS Start: " + icsStart();
         result = result + "\nICS End:   " + icsEnd();
         result = result + "\nICS Recur: " + icsRecurring()+ icsEndRecur();
      
         return result;
      }
   }